home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGNG_C / TPTC17GS.LZH / TPCSCAN.INC < prev    next >
Text File  |  1988-05-03  |  21KB  |  903 lines

  1.  
  2. (*
  3.  * TPTC - Turbo Pascal to C translator
  4.  *
  5.  * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
  6.  *
  7.  *)
  8.  
  9.  
  10. (********************************************************************)
  11. (*
  12.  * lexical scanner
  13.  *
  14.  *)
  15.  
  16. (********************************************************************)
  17. procedure getchar;
  18.    {consume the current char and get the next one}
  19. var
  20.    stack: char;
  21. begin
  22.    if ofs(stack) < minstack then
  23.       fatal('Out of stack space');
  24.  
  25.    while (srclevel > 0) and eof(srcfd[srclevel]) do
  26.    begin
  27.       if not linestart then putline;
  28.       putln('/* TPTC: end of '+srcfiles[srclevel]+' */');
  29.       
  30.       if (not redirect) and (not debug) then
  31.          writeln(^M,srcfiles[srclevel],'(',srclines[srclevel],')');
  32.       
  33.       close(srcfd[srclevel]);
  34.       freemem(inbuf[srclevel],inbufsiz);
  35.  
  36.       dec(srclevel);
  37.       statustime := 0;
  38.    end;
  39.     
  40.    if (srclevel = 0) and eof(srcfd[srclevel]) then
  41.       nextc := '.'
  42.    else
  43.    {$i-} read(srcfd[srclevel], nextc); {$i+}
  44.  
  45.    if nextc = ^J then
  46.    begin
  47.       inc(srclines[srclevel]);
  48.       inc(srctotal);
  49.       
  50.       mark_time(curtime);
  51.       if (curtime >= statustime) or debug then
  52.       begin
  53.          if debug then 
  54.             writeln
  55.          else
  56.          if not redirect then
  57.             write(^M);
  58.  
  59.          if debug or not redirect then
  60.             write(srcfiles[srclevel],'(',srclines[srclevel],')');
  61.  
  62.          statustime := curtime+statrate;
  63.          abortcheck;
  64.       end;
  65.    end;
  66. end;
  67.  
  68.  
  69. (********************************************************************)
  70. function usec: char;
  71.    {use up the current character(return it) and get
  72.     the next one from the input stream}
  73. var
  74.    c: char;
  75. begin
  76.    c := nextc;
  77.    getchar;
  78.    usec := c;
  79. end;
  80.  
  81.  
  82. (********************************************************************)
  83. function newc(n: string40): string40;
  84.    {replace the current character with a different one and get the next
  85.     character from the input stream}
  86. var
  87.    c: char;
  88. begin
  89.    c := nextc;
  90.    getchar;
  91.    newc := n;
  92. end;
  93.  
  94.  
  95. (********************************************************************)
  96. procedure addc;
  97.    {add current character to ltok and consume it}
  98. begin
  99.    inc(ltok[0]);
  100.    ltok[length(ltok)] := nextc;
  101.    getchar;
  102.    
  103.    {ltok := ltok + usec;   <--same thing but slower}
  104. end;
  105.  
  106.  
  107. (********************************************************************)
  108. procedure concat_tokens;
  109.    {concatenate the next token and the current token}
  110. var
  111.    cur: string;
  112. begin
  113.    cur := ltok;
  114.    ltok := nextc;
  115.    toktype := unknown;
  116.    scan_tok;
  117.  
  118.    ltok := copy(cur,1,length(cur)-1) + copy(ltok,2,255);
  119.    ltok[1] := '"';
  120.    ltok[length(ltok)] := '"';
  121.    toktype := strng;
  122. end;
  123.  
  124.  
  125. (********************************************************************)
  126. procedure scan_ident;
  127.    {scan an identifier; output is ltok; nextc is first character following
  128.     the identifier; toktype = identifier;  this is the protocol for all of
  129.     the scan_xxxx procedures in the lexical analyzer}
  130. begin
  131.  
  132.    toktype := unknown;
  133.    ltok := '';
  134.  
  135.    repeat
  136.       case nextc of
  137.          'A'..'Z':
  138.             begin
  139.                if map_lower then
  140.                   nextc := chr( ord(nextc)+32 );
  141.                addc;
  142.             end;
  143.  
  144.          'a'..'z', '0'..'9', '_','@':
  145.             addc;
  146.  
  147.          else
  148.             toktype := identifier;
  149.       end;
  150.  
  151.    until toktype = identifier;
  152. end;
  153.  
  154.  
  155.  
  156. (********************************************************************)
  157. procedure scan_preproc;
  158.    {scan a tshell preprocessor directive;  same syntax as C already}
  159. begin
  160.    repeat
  161.       puts(nextc);
  162.       getchar;
  163.    until nextc = ^M;
  164.  
  165.    getchar;
  166.    putline;
  167.    toktype := unknown;
  168. end;
  169.  
  170.  
  171. (********************************************************************)
  172. function numlit(n: integer): anystring;
  173.    {convert a number into a character literal if possible}
  174. var
  175.    lit: string[6];
  176.    
  177.    {convert an integer into a c style numeric character literal}
  178.    function digit(n: integer): char;
  179.       (* convert an integer into a hex digit *)
  180.    begin
  181.       n := n and 15;
  182.       if n > 9 then n := n + 7;
  183.       digit := chr( n + ord('0') );
  184.    end;
  185.  
  186. begin
  187.    lit := '''\?''';
  188.  
  189.    case n of
  190.      $07:   lit[3] := 'a';
  191.      $08:   lit[3] := 'b';
  192.      $09:   lit[3] := 't';
  193.      $0a:   lit[3] := 'n';
  194.      $0b:   lit[3] := 'v';
  195.      $0c:   lit[3] := 'f';
  196.      $0d:   lit[3] := 'r';
  197.  
  198.      32..126,128..254:
  199.             lit := ''''+chr(n)+'''';
  200.  
  201.      else   begin
  202.                lit := '''\x??''';
  203.                lit[4] := digit(n shr 4);
  204.                lit[5] := digit(n);
  205.             end;
  206.    end;
  207.  
  208.    numlit := lit;
  209.    toktype := chars;
  210. end;
  211.  
  212.  
  213. (********************************************************************)
  214. procedure scan_number;
  215.    {scan a number;  this also processes #nnn character literals, which are
  216.     converted into octal character literals.  imbedded periods are processed,
  217.     and a special condition is noted for trailing periods.  this is needed
  218.     for scanning the ".." keyword when used after numbers.  an ungetchar
  219.     facility would be more general, but isn't needed anywhere else.
  220.     in pascal/mt+, #nnn is translated into nnnL }
  221. var
  222.    hasdot:     boolean;
  223.    charlit:    boolean;
  224.    islong:     boolean;
  225.    ishex:      boolean;
  226.  
  227. begin
  228.    hasdot := false;
  229.    islong := false;
  230.    charlit := false;
  231.    ishex := false;
  232.    toktype := number;
  233.    
  234. (* check for preprocessor directives, character literals or long literals *)
  235.    if nextc = '#' then
  236.    begin
  237.       ltok := '';
  238.       if mt_plus then
  239.          islong := true
  240.       else
  241.          charlit := true;
  242.    end;
  243.  
  244.    getchar;
  245.  
  246. (* check for preprocessor directives *)
  247.    if tshell and charlit and (nextc >= 'a') and (nextc <= 'z') then
  248.    begin
  249.       puts('#');
  250.       scan_preproc;
  251.    end
  252.    else
  253.  
  254.    repeat
  255.       if (nextc = '-') and (upcase(ltok[length(ltok)]) = 'E') then
  256.          addc;
  257.  
  258.       case nextc of
  259.          'e','E':
  260.             begin
  261.                if not ishex then
  262.                   toktype := realnumber;
  263.                addc;
  264.             end;
  265.  
  266.          '$':
  267.             begin
  268.                ishex := true;
  269.                addc;
  270.             end;
  271.             
  272.          '0'..'9',
  273.          'a'..'f','A'..'F':
  274.             addc;
  275.  
  276.          '.':
  277.             if hasdot then
  278.             begin
  279.                toktype := number;
  280.                if ltok[length(ltok)] = '.' then
  281.                begin
  282.                   ltok[0] := pred(ltok[0]);  {remove trailing ., part of ..}
  283.                   if charlit then
  284.                      ltok := numlit(htoi(ltok));
  285.                   extradot := true;
  286.                end;
  287.                exit;
  288.             end
  289.             else
  290.  
  291.             begin
  292.                hasdot := true;
  293.                toktype := realnumber;
  294.                addc;
  295.             end;
  296.  
  297.          else
  298.             begin
  299.                if charlit then
  300.                begin
  301.                   ltok := numlit(htoi(ltok));
  302.                   if (nextc = '''') or (nextc = '^') or (nextc = '#') then
  303.                      concat_tokens;
  304.                   exit;
  305.                end;
  306.                
  307.                if ltok[1] = '$' then
  308.                begin
  309.                   ltok := '0x' + copy(ltok,2,99);
  310.                   toktype := number;
  311.                end;
  312.  
  313.                if (toktype <> realnumber) and 
  314.                   (islong or (abs(atol(ltok)) > maxint)) then
  315.                begin
  316.                   ltok := ltok + 'L';
  317.                   toktype := longnumber;
  318.                end;
  319.  
  320.                exit;
  321.             end;
  322.       end;
  323.  
  324.    until true=false;
  325. end;
  326.  
  327.  
  328. (********************************************************************)
  329. procedure scan_hat;
  330.    {scan tokens starting with ^ - returns ^X as a character literal 
  331.     corresponding to the specified control character.  returns ^ident as
  332.     an identifier with the leading ^ intact.  also scans ^. and ^[.}
  333. var
  334.    c: char;
  335.  
  336. begin
  337.    getchar;
  338.  
  339.    if ((nextc = '.') or (nextc = '[')) and 
  340.       ((ptoktype = identifier) or (ptok[1] = ']')) then
  341.    begin
  342.       ltok := '^' + usec;     {^. or ^[}
  343.       exit;
  344.    end;
  345.  
  346.    case nextc of
  347.       '@','['..'`':
  348.          ltok := usec;
  349.          
  350.       'A'..'Z','a'..'z':
  351.          begin
  352.             ltok := nextc;
  353.             scan_ident;
  354.          end;
  355.        else
  356.          exit;
  357.    end;
  358.  
  359.    if length(ltok) = 1 then      {^c = control char}
  360.    begin
  361.       ltok := numlit( ord(upcase(ltok[1])) - ord('@') );
  362.       if (nextc = '''') or (nextc = '^') or (nextc = '#') then
  363.          concat_tokens;
  364.    end
  365.    else
  366.       ltok := '^' + ltok;        {^ident = pointer to ident}
  367.  
  368. end;
  369.  
  370.  
  371. (********************************************************************)
  372. procedure scan_dot;
  373.    {scans tokens starting with "."; knows about the 'extra dot' condition
  374.     that comes up in number scanning.  returns a token of either '.' or '..'}
  375. begin
  376.    getchar;
  377.  
  378.    if (nextc = '.') or extradot then
  379.    begin
  380.       ltok := '..';
  381.       extradot := false;
  382.    end;
  383.  
  384.    if nextc = '.' then
  385.       getchar;
  386. end;
  387.  
  388.  
  389. (********************************************************************)
  390. procedure scan_string;
  391.    {scans a literal string.  processes imbedded quotes ala pascal.  translates
  392.     the string into a C string with the proper escapes on imbedded quotes.
  393.     converts single character strings into character constants.  these are
  394.     sometimes converted back to strings when the parser needs to}
  395. begin
  396.    toktype := unknown;
  397.    ltok := '"';
  398.    getchar;
  399.  
  400.    repeat
  401.       case nextc of
  402.          ^J,^M:
  403.             begin
  404.                error_message('Closing quote expected (scan_string)');
  405.                toktype := strng;
  406.             end;
  407.       
  408.          '''':
  409.             begin
  410.                getchar;     {consume the quote}
  411.       
  412.                if nextc = '''' then
  413.                   addc
  414.                   {double quotes are coded as a single quote}
  415.                else
  416.       
  417.                begin        {end of string}
  418.                   ltok := ltok + '"';
  419.                   toktype := strng;
  420.                end;
  421.             end;
  422.       
  423.          '"':  ltok := ltok + newc('\"');
  424.          '\':  ltok := ltok + newc('\\');
  425.  
  426.          else  addc;
  427.       end;
  428.  
  429.    until toktype = strng;
  430.  
  431.    if length(ltok) = 3 then
  432.    begin
  433.       ltok[1] := '''';
  434.       ltok[3] := '''';
  435.       toktype := chars;
  436.    end;
  437.  
  438.    {convert string escapes into character escapes}
  439.    if ltok = '"\""' then
  440.    begin
  441.       ltok := '''"''';
  442.       toktype := chars;
  443.    end
  444.    else
  445.  
  446.    if (ltok = '"''"') or (ltok = '''''''') then
  447.    begin
  448.       ltok := '''\''''';
  449.       toktype := chars;
  450.    end
  451.    else
  452.  
  453.    if (ltok = '"\\"') then
  454.    begin
  455.       ltok := '''\\''';
  456.       toktype := chars;
  457.    end;
  458.  
  459.    {allow consecutive control character literals}
  460.    if (nextc = '^') or (nextc = '#') then
  461.       concat_tokens;
  462. end;
  463.  
  464.  
  465. (********************************************************************)
  466. procedure scan_pragma(var isinclude: anystring);
  467.    {scans a turbo pascal compiler option and translates it into a comment.
  468.     include directive is translated into the #include.
  469.     returns with the first non-blank after the pragma}
  470. var
  471.    code: anystring;
  472.    prag: anystring;
  473.    arg:  anystring;
  474.  
  475.    procedure scanword(var dest: anystring);
  476.    begin
  477.       dest := '       ';  {insure dest[2] is initialized}
  478.       dest := '';
  479.       while true do
  480.       case nextc of
  481.          ' ', '*', '}', ',':
  482.             exit;
  483.          else
  484.          begin
  485.             dest := dest + upcase(nextc);
  486.             getchar;
  487.          end;
  488.       end;
  489.    end;
  490.    
  491. begin
  492.    isinclude := '';
  493.    
  494.    repeat
  495.       if nextc = ',' then
  496.          newline;
  497.  
  498.       getchar;   {consume the $ or ,}
  499.    
  500.       {get the progma code}
  501.       scanword(code);
  502.       
  503.       if nextc = ' ' then
  504.       begin
  505.          getchar;
  506.          scanword(arg);
  507.       end
  508.       else
  509.          arg := '';
  510.       
  511.       if code[2] = '+' then
  512.          arg := 'ON'
  513.       else
  514.       if code[2] = '-' then
  515.          arg := 'OFF';
  516.  
  517.       prag := '/* '+code[1]+'(' + arg + ')' + ' */';
  518.       
  519.       case code[1] of
  520.  
  521.          'D':  if code[2] = 'E' then
  522.                   prag := '#define '+arg;
  523.                
  524.          'E':  if code[2] = 'N' then
  525.                   prag := '#endif'
  526.                else
  527.                if code[2] = 'L' then
  528.                   prag := '#else';
  529.                
  530.          'I':  if code[2] = ' ' then
  531.                begin
  532.                   if pos('.',arg) = 0 then
  533.                      arg := arg + '.PAS';
  534.                   prag := '#include "' + arg + '"   ';
  535.                            
  536.                   if includeinclude then
  537.                   begin
  538.                      prag := '';
  539.                      isinclude := arg;
  540.                   end;
  541.                end
  542.                else
  543.                
  544.                if code[2] = 'F' then
  545.                begin
  546.                   if code[3] = 'N' then
  547.                      prag := '#ifndef '+arg
  548.                   else
  549.                      prag := '#ifdef '+arg;
  550.                end;
  551.  
  552.          'U':  if code[2] = 'N' then
  553.                   prag := '#undef '+arg;
  554.                
  555.       end;
  556.  
  557.       puts(prag);
  558.       puts('   ');
  559.  
  560.       while nextc = ' ' do
  561.          getchar;
  562.  
  563.    until nextc <> ',';
  564.  
  565. end;
  566.  
  567.  
  568. (********************************************************************)
  569. procedure open_include(name: anystring);
  570. begin
  571.    if length(name) = 0 then exit;
  572.    
  573.    inc(srctotal);
  574.    inc(objtotal);
  575.  
  576.    inc(srclevel);
  577.    if srclevel > maxincl then
  578.       fatal('Includes nested too deeply');
  579.       
  580.    srcfiles[srclevel] := name;
  581.    srclines[srclevel] := 1;
  582.    
  583.    assign(srcfd[srclevel],name);
  584.    {$I-} reset(srcfd[srclevel]); {$I+}
  585.    if ioresult <> 0 then
  586.    begin
  587.       dec(srclevel);
  588.       ltok := name;
  589.       warning('Missing include file');
  590.    end
  591.    else
  592.  
  593.    begin
  594.       if not linestart then putline;
  595.       putln('/* TPTC: include '+name+' */');
  596.  
  597.       if maxavail-300 <= inbufsiz then
  598.       begin
  599.          ltok := name;
  600.          fatal('Out of memory');
  601.       end;
  602.          
  603.       getmem(inbuf[srclevel],inbufsiz);
  604.       SetTextBuf(srcfd[srclevel],inbuf[srclevel]^,inbufsiz);
  605.    end;
  606.    
  607.    if debug then
  608.       writeln
  609.    else
  610.    if not redirect then
  611.       write(^M,'':40,^M);
  612.       
  613.    statustime := 0;
  614. end;
  615.  
  616.  
  617. (********************************************************************)
  618. procedure scan_curlycomment;
  619.    {processes a curly-brace enclosed comment}
  620. var
  621.    isinclude: anystring;
  622.    
  623. begin
  624.    toktype := comment;
  625.    getchar;   {consume the open comment}
  626.  
  627.    isinclude := '';
  628.    if nextc = '$' then
  629.       scan_pragma(isinclude);
  630.  
  631.    if nextc = '}' then
  632.    begin
  633.       getchar;
  634.       open_include(isinclude);
  635.       exit;
  636.    end;
  637.  
  638.    if pass_comments then
  639.       puts('  /* ');
  640.  
  641.    while nextc <> '}' do
  642.    begin
  643.       if pass_comments then
  644.          puts(nextc);
  645.       getchar;
  646.    end;
  647.  
  648.    if pass_comments then
  649.    begin
  650.       puts(' */ ');
  651.       if nospace then newline;
  652.    end;
  653.  
  654.    getchar;   {consume the close comment}
  655.    open_include(isinclude);
  656. end;
  657.  
  658.  
  659. (********************************************************************)
  660. procedure scan_parencomment;
  661.    {process a (* enclosed comment}
  662. var
  663.    isinclude: anystring;
  664.    
  665. begin
  666.    toktype := comment;
  667.    getchar;   {consume the *}
  668.  
  669.    isinclude := '';
  670.    if nextc = '$' then
  671.       scan_pragma(isinclude);
  672.  
  673.    if pass_comments then
  674.       puts('/*');
  675.  
  676.    repeat
  677.       if pass_comments then
  678.          puts(nextc);
  679.  
  680.       if nextc = '*' then
  681.       begin
  682.          getchar;
  683.  
  684.          if nextc = ')' then
  685.          begin
  686.             getchar;
  687.             if pass_comments then
  688.             begin
  689.                puts('/ ');
  690.                if nospace then putline;
  691.             end;
  692.             open_include(isinclude);
  693.             exit;
  694.          end;
  695.       end
  696.       else
  697.          getchar;
  698.  
  699.    until true=false;
  700. end;
  701.  
  702.  
  703. (********************************************************************)
  704. procedure scan_blanks;
  705.    {scan white space.  this procedure sometimes passes whitespace to the
  706.     output.  it keeps track of the indentation of the current line so it
  707.     can be used by newline}
  708. var
  709.    valid:         boolean;
  710.  
  711. begin
  712.    linestart := false;
  713.    delim := '';
  714.    valid := false;
  715.  
  716.    repeat
  717.  
  718.       case nextc of
  719.          ^M:     getchar;
  720.  
  721.          ^J:     begin
  722.                     if nospace = false then
  723.                        putline;
  724.                     
  725.                     delim := '';
  726.                     linestart := true;
  727.                     getchar;
  728.                  end;
  729.  
  730.          ' ',^I,^@,^L:
  731.                  delim := delim + usec;
  732.  
  733.          '#','\':
  734.                  if linestart and (tshell or (nextc = '\')) then
  735.                  begin
  736.                     if nextc = '\' then
  737.                        getchar;
  738.  
  739.                     puts(delim);     {pass preprocessor directives}
  740.                     delim := '';     {without change (single-line only)}
  741.  
  742.                     while nextc <> ^M do
  743.                     begin
  744.                        puts(nextc);
  745.                        getchar;
  746.                     end;
  747.  
  748.                     getchar;           {consume the cr}
  749.                     if nextc = ^J then
  750.                        getchar;           {consume the lf}
  751.                     putline;
  752.                  end
  753.                  else
  754.                     valid := true;
  755.          else
  756.                  valid := true;
  757.       end;
  758.    until valid;
  759.  
  760.    if linestart then
  761.    begin
  762.       spaces := delim;
  763.       if nospace=false then
  764.          puts(spaces);
  765.       linestart := true;
  766.    end;
  767.  
  768. end;
  769.  
  770.  
  771. (********************************************************************)
  772. procedure scan_tok;
  773.    {scans the next lexical token; returns the token in ltok and toktype}
  774. begin
  775.    scan_blanks;
  776.  
  777.    toktype := unknown;
  778.    ltok := nextc;
  779.  
  780.    case nextc of
  781.       'a'..'z', 
  782.       '_', 'A'..'Z': scan_ident;
  783.  
  784.       '$':           scan_number;
  785.       '0'..'9':      scan_number;
  786.  
  787.       '''':          scan_string;
  788.  
  789.       '^':           scan_hat;
  790.  
  791.       '#':           begin
  792.                         scan_number;
  793.                         if toktype = unknown then
  794.                            scan_tok;         {in case of #directive}
  795.                      end;
  796.  
  797.  
  798.       '<':           begin
  799.                         getchar;
  800.                         if (nextc = '>') or (nextc = '=') then
  801.                            ltok := '<' + usec;
  802.                      end;
  803.  
  804.       '>':           begin
  805.                         getchar;
  806.                         if nextc = '=' then
  807.                            ltok := '>' + usec;
  808.                      end;
  809.  
  810.       ':':           begin
  811.                         getchar;
  812.                         if nextc = '=' then
  813.                            ltok := ':' + usec;
  814.                      end;
  815.  
  816.       '.':           scan_dot;
  817.  
  818.       '{':           scan_curlycomment;
  819.  
  820.       '(':           begin
  821.                         getchar;
  822.                         if nextc = '*' then
  823.                            scan_parencomment;
  824.                      end;
  825.  
  826.       else           getchar;   {consume the unknown char}
  827.    end;
  828. end;
  829.  
  830.  
  831. (********************************************************************)
  832. procedure gettok;
  833.    {get the next input token;  this is the top level of the lexical analyzer.
  834.     it returns ltok, tok(ltok in upper case), toktype.  it translates BEGIN
  835.     and END into braces; it checks for statement and section keywords}
  836. var
  837.    i:             integer;
  838.  
  839. begin
  840.    ptoktype := toktype;
  841.    ptok := tok;
  842.    cursym := nil;
  843.    
  844.    repeat
  845.       scan_tok;
  846.    until toktype <> comment;
  847.    tok := ltok;
  848.  
  849.    if debug then write(' {',ltok,'}');
  850.  
  851.    if toktype = identifier then
  852.    begin
  853.       cursym := nil;
  854.       stoupper(tok);
  855.  
  856.       if (length(tok) = 5) and (tok = 'BEGIN') then
  857.       begin
  858.          tok := '{';
  859.          ltok := tok;
  860.          toktype := keyword;
  861.          exit;
  862.       end
  863.       else
  864.  
  865.       if (length(tok) = 3) and (tok = 'END') then
  866.       begin
  867.          tok := '}';
  868.          ltok := tok;
  869.          toktype := keyword;
  870.          exit;
  871.       end;
  872.  
  873.       (* check for statement keywords *)
  874.       i := 0;
  875.       repeat
  876.          inc(i);
  877.  
  878.          if length(tok) = length(keywords[i]) then
  879.             if tok[1] = keywords[i][1] then              {hack for speed}
  880.                if tok = keywords[i] then
  881.                   toktype := keyword;
  882.  
  883.       until (i = nkeywords) or (toktype = keyword);
  884.  
  885.       (* get symbol table information for this item *)
  886.       cursym := locatesym(tok);
  887.    end;
  888. end;
  889.  
  890.  
  891. (********************************************************************)
  892. function usetok: string80;
  893.    {return (use) and consume current token}
  894. var
  895.    tv: string80;
  896. begin
  897.    tv := ltok;
  898.    gettok;
  899.    usetok := tv;
  900. end;
  901.  
  902.  
  903.